home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Tutorials / Tut03_EnumHosts / EnumHosts.cpp next >
C/C++ Source or Header  |  2001-10-08  |  18KB  |  559 lines

  1. //----------------------------------------------------------------------------
  2. // File: EnumHosts.cpp
  3. //
  4. // Desc: This simple program builds upon the last tutorial and adds enumerating 
  5. //       the hosts at a given target address
  6. //
  7. // Copyright (c) 2000-2001 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define INITGUID
  10. #define _WIN32_DCOM
  11. #include <stdio.h>
  12. #include <conio.h>
  13. #include <dplay8.h>
  14.  
  15.  
  16.  
  17.  
  18. //-----------------------------------------------------------------------------
  19. // App specific structures 
  20. //-----------------------------------------------------------------------------
  21. struct HOST_NODE
  22. {
  23.     DPN_APPLICATION_DESC*   pAppDesc;
  24.     IDirectPlay8Address*    pHostAddress;
  25.     WCHAR*                  pwszSessionName;
  26.  
  27.     HOST_NODE*             pNext;
  28. };
  29.  
  30.  
  31. //-----------------------------------------------------------------------------
  32. // Global variables
  33. //-----------------------------------------------------------------------------
  34. IDirectPlay8Peer*                   g_pDP               = NULL;
  35. IDirectPlay8Address*                g_pDeviceAddress    = NULL;
  36. IDirectPlay8Address*                g_pHostAddress      = NULL;
  37. BOOL                                g_bHost;
  38. HOST_NODE*                          g_pHostList         = NULL;
  39. CRITICAL_SECTION                    g_csHostList;
  40.  
  41.  
  42. // This GUID allows DirectPlay to find other instances of the same game on
  43. // the network.  So it must be unique for every game, and the same for 
  44. // every instance of that game.  // {358E1C8D-DB4A-4867-B2C3-DEF3F5046B17}
  45. GUID g_guidApp = { 0x358e1c8d, 0xdb4a, 0x4867, { 0xb2, 0xc3, 0xde, 0xf3, 0xf5, 0x4, 0x6b, 0x17 } };
  46.  
  47.  
  48. //-----------------------------------------------------------------------------
  49. // Function-prototypes
  50. //-----------------------------------------------------------------------------
  51. HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);
  52. BOOL    IsServiceProviderValid(const GUID* pGuidSP);
  53. HRESULT InitDirectPlay();
  54. HRESULT CreateDeviceAddress();
  55. HRESULT CreateHostAddress(WCHAR* pwszHost);
  56. HRESULT HostSession();
  57. HRESULT EnumDirectPlayHosts();
  58. void    CleanupDirectPlay();
  59.  
  60.  
  61. //-----------------------------------------------------------------------------
  62. // Miscellaneous helper functions
  63. //-----------------------------------------------------------------------------
  64. #define SAFE_DELETE(p)          {if(p) {delete (p);     (p)=NULL;}}
  65. #define SAFE_DELETE_ARRAY(p)    {if(p) {delete[] (p);   (p)=NULL;}}
  66. #define SAFE_RELEASE(p)         {if(p) {(p)->Release(); (p)=NULL;}}
  67.  
  68. #define USER_HOST 1
  69. #define USER_CONNECT 2
  70.  
  71.  
  72.  
  73.  
  74. //-----------------------------------------------------------------------------
  75. // Name: main()
  76. // Desc: Entry point for the application.  
  77. //-----------------------------------------------------------------------------
  78. int main(int argc, char* argv[], char* envp[])
  79. {
  80.     HRESULT hr;
  81.     int     iUserChoice;
  82.  
  83.     // Init COM so we can use CoCreateInstance
  84.     CoInitializeEx(NULL, COINIT_MULTITHREADED);
  85.  
  86.     // Init the DirectPlay system
  87.     if( FAILED( hr = InitDirectPlay() ) )
  88.     {
  89.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  90.         goto LFail;
  91.     }
  92.  
  93.     InitializeCriticalSection(&g_csHostList);
  94.  
  95.     // Get the necessary user input on whether they are hosting or connecting
  96.     do
  97.     {
  98.         printf("Please select one.\n1.  Host\n2.  Connect\n");
  99.         scanf("%d", &iUserChoice);
  100.     } while (iUserChoice != USER_HOST && iUserChoice != USER_CONNECT);
  101.  
  102.  
  103.     if( FAILED( hr = CreateDeviceAddress() ) )
  104.     {
  105.         printf("Failed CreatingDeviceAddress:  0x%X\n", hr);
  106.         goto LFail;
  107.     }
  108.  
  109.     if( iUserChoice == USER_HOST )
  110.     {
  111.         if( FAILED( hr = HostSession() ) )
  112.         {
  113.             printf("Failed Hosting:  0x%X\n", hr);
  114.             goto LFail;
  115.         }
  116.     }
  117.     else
  118.     {
  119.         if( FAILED( hr = EnumDirectPlayHosts() ) )
  120.         {
  121.             printf("Failed Enumerating Host:  0x%X\n", hr);
  122.             goto LFail;
  123.         }
  124.     }
  125.  
  126. LFail:
  127.     CleanupDirectPlay();
  128.  
  129.     // Cleanup COM
  130.     CoUninitialize();
  131.  
  132.     return 0;
  133. }
  134.  
  135.  
  136.  
  137.  
  138. //-----------------------------------------------------------------------------
  139. // Name: InitDirectPlay()
  140. // Desc: Initialize DirectPlay
  141. //-----------------------------------------------------------------------------
  142. HRESULT InitDirectPlay()
  143. {
  144.     HRESULT     hr = S_OK;
  145.  
  146.     // Create the IDirectPlay8Peer Object
  147.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, 
  148.                                        CLSCTX_INPROC_SERVER,
  149.                                        IID_IDirectPlay8Peer, 
  150.                                        (LPVOID*) &g_pDP ) ) )
  151.     {
  152.         printf("Failed Creating the IDirectPlay8Peer Object:  0x%X\n", hr);
  153.         goto LFail;
  154.     }
  155.  
  156.     // Init DirectPlay
  157.     if( FAILED( hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
  158.     {
  159.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  160.         goto LFail;
  161.     }
  162.     
  163.     // Ensure that TCP/IP is a valid Service Provider
  164.     if( FALSE == IsServiceProviderValid(&CLSID_DP8SP_TCPIP ) )
  165.     {
  166.         hr = E_FAIL;
  167.         printf("Failed validating CLSID_DP8SP_TCPIP");
  168.         goto LFail;
  169.     }
  170.  
  171. LFail:
  172.     return hr;
  173. }
  174.  
  175.  
  176.  
  177.  
  178. //-----------------------------------------------------------------------------
  179. // Name: IsServiceProviderValid()
  180. // Desc: Return TRUE if the service provider is valid
  181. //-----------------------------------------------------------------------------
  182. BOOL IsServiceProviderValid(const GUID* pGuidSP)
  183. {
  184.     HRESULT                     hr;
  185.     DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo = NULL;
  186.     DWORD                       dwItems = 0;
  187.     DWORD                       dwSize = 0;
  188.  
  189.     hr = g_pDP->EnumServiceProviders( &CLSID_DP8SP_TCPIP, NULL, NULL, 
  190.                                       &dwSize, &dwItems, 0);
  191.  
  192.     if( hr != DPNERR_BUFFERTOOSMALL)
  193.     {
  194.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  195.         goto LFail;
  196.     }
  197.  
  198.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  199.  
  200.     if( FAILED( hr = g_pDP->EnumServiceProviders( &CLSID_DP8SP_TCPIP, NULL, pdnSPInfo, 
  201.                                                  &dwSize, &dwItems, 0 ) ) )
  202.     {
  203.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  204.         goto LFail;
  205.     }
  206.  
  207.     // There are no items returned so the requested SP is not available
  208.     if( dwItems == 0)
  209.     {
  210.         hr = E_FAIL;
  211.     }
  212.  
  213. LFail:
  214.     SAFE_DELETE_ARRAY(pdnSPInfo);
  215.     
  216.     if( SUCCEEDED(hr) )
  217.         return TRUE;
  218.     else
  219.         return FALSE;
  220. }
  221.  
  222.  
  223.  
  224.  
  225. //-----------------------------------------------------------------------------
  226. // Name: DirectPlayMessageHandler
  227. // Desc: Handler for DirectPlay messages.  This tutorial only responds to the
  228. //       DPN_MSGID_ENUM_HOSTS_RESPONSE message.
  229. //-----------------------------------------------------------------------------
  230. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, 
  231.                                          PVOID pMsgBuffer )
  232. {
  233.     HRESULT     hr = S_OK;
  234.  
  235.     switch( dwMessageId )
  236.     {
  237.         case DPN_MSGID_ENUM_HOSTS_RESPONSE:
  238.         {
  239.             PDPNMSG_ENUM_HOSTS_RESPONSE     pEnumHostsResponseMsg;
  240.             const DPN_APPLICATION_DESC*     pAppDesc;
  241.             HOST_NODE*                      pHostNode = NULL;
  242.             WCHAR*                          pwszSession = NULL;
  243.         
  244.             pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE) pMsgBuffer;
  245.             pAppDesc = pEnumHostsResponseMsg->pApplicationDescription;
  246.         
  247.             // Insert each host response if it isn't already present
  248.             EnterCriticalSection(&g_csHostList);
  249.         
  250.             for (pHostNode = g_pHostList; pHostNode; pHostNode = pHostNode->pNext)
  251.             {
  252.                 if( pAppDesc->guidInstance == pHostNode->pAppDesc->guidInstance)
  253.                 {
  254.                     // This host is already in the list
  255.                     pHostNode = NULL;
  256.                     goto Break_ENUM_HOSTS_RESPONSE;
  257.                 }
  258.             }
  259.         
  260.             // This host session is not in the list then so insert it.
  261.             pHostNode = new HOST_NODE;
  262.             if( pHostNode == NULL)
  263.             {
  264.                 goto Break_ENUM_HOSTS_RESPONSE;
  265.             }
  266.         
  267.             ZeroMemory(pHostNode, sizeof(HOST_NODE));
  268.         
  269.             // Copy the Host Address
  270.             if( FAILED( pEnumHostsResponseMsg->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ) )
  271.             {
  272.                 goto Break_ENUM_HOSTS_RESPONSE;
  273.             }
  274.         
  275.             pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
  276.         
  277.             if( pHostNode == NULL)
  278.             {
  279.                 goto Break_ENUM_HOSTS_RESPONSE;
  280.             }
  281.         
  282.             ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
  283.             memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
  284.         
  285.             // Null out all the pointers we aren't copying
  286.             pHostNode->pAppDesc->pwszSessionName = NULL;
  287.             pHostNode->pAppDesc->pwszPassword = NULL;
  288.             pHostNode->pAppDesc->pvReservedData = NULL;
  289.             pHostNode->pAppDesc->dwReservedDataSize = 0;
  290.             pHostNode->pAppDesc->pvApplicationReservedData = NULL;
  291.             pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
  292.         
  293.             if( pAppDesc->pwszSessionName)
  294.             {
  295.                 pwszSession = new WCHAR[wcslen(pAppDesc->pwszSessionName) + 1];
  296.             
  297.                 if( pwszSession)
  298.                 {
  299.                     wcscpy(pwszSession, pAppDesc->pwszSessionName);
  300.                 }
  301.             }
  302.         
  303.             pHostNode->pwszSessionName = pwszSession;
  304.         
  305.             // Insert it onto the front of the list
  306.             pHostNode->pNext = g_pHostList ? g_pHostList->pNext : NULL;
  307.             g_pHostList = pHostNode;
  308.             pHostNode = NULL;
  309.         
  310. Break_ENUM_HOSTS_RESPONSE:
  311.             LeaveCriticalSection(&g_csHostList);       
  312.  
  313.             if( pHostNode )
  314.             {
  315.                 SAFE_RELEASE(pHostNode->pHostAddress);           
  316.                 SAFE_DELETE(pHostNode->pAppDesc);            
  317.                 delete pHostNode;
  318.             }
  319.         
  320.             break;
  321.         }
  322.     }
  323.     return hr;
  324. }
  325.  
  326.  
  327.  
  328.  
  329. //-----------------------------------------------------------------------------
  330. // Name: EnumDirectPlayHosts()
  331. // Desc: Enumerates the hosts
  332. //-----------------------------------------------------------------------------
  333. HRESULT EnumDirectPlayHosts()
  334. {
  335.     HRESULT                 hr = S_OK;
  336.     WCHAR                   wszHost[128];
  337.     DPN_APPLICATION_DESC    dpAppDesc;
  338.     WCHAR*                  pwszURL = NULL;
  339.     HOST_NODE*              pHostNode = NULL;
  340.     DWORD                   dwNumChars = 0;
  341.  
  342.     // Prompt for the hostname/ip
  343.     printf("\nPlease enter the IP address of host:\n");
  344.     wscanf(L"%ls", wszHost);
  345.  
  346.     if( FAILED( hr = CreateHostAddress( wszHost ) ) )
  347.     {
  348.         printf("Failed Creating Host Address:  0x%X\n", hr);
  349.         goto LFail;
  350.     }
  351.  
  352.  
  353.     // Now set up the Application Description
  354.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  355.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  356.     dpAppDesc.guidApplication = g_guidApp;
  357.  
  358.     // We now have the host address so lets enum
  359.     if( FAILED( hr = g_pDP->EnumHosts( &dpAppDesc,               // pApplicationDesc
  360.                                        g_pHostAddress,         // pdpaddrHost
  361.                                        g_pDeviceAddress,       // pdpaddrDeviceInfo
  362.                                        NULL, 0,                // pvUserEnumData, size
  363.                                        4,                      // dwEnumCount
  364.                                        0,                      // dwRetryInterval
  365.                                        0,                      // dwTimeOut
  366.                                        NULL,                   // pvUserContext
  367.                                        NULL,                   // pAsyncHandle
  368.                                        DPNENUMHOSTS_SYNC ) ) ) // dwFlags
  369.     {
  370.         printf("Failed Enumerating the Hosts:  0x%X\n", hr);
  371.         goto LFail;
  372.     }
  373.  
  374.  
  375.     // Go through and print out all the hosts URL's that we found
  376.     EnterCriticalSection(&g_csHostList);
  377.  
  378.     for (pHostNode = g_pHostList; pHostNode; pHostNode = pHostNode->pNext, dwNumChars = 0)
  379.     {
  380.         hr = pHostNode->pHostAddress->GetURLW(NULL, &dwNumChars);
  381.  
  382.         if( hr == DPNERR_BUFFERTOOSMALL)
  383.         {
  384.             pwszURL = new WCHAR[dwNumChars];
  385.  
  386.             if( pwszURL && SUCCEEDED(hr = pHostNode->pHostAddress->GetURLW(pwszURL, &dwNumChars ) ) )
  387.             {
  388.                 printf("Found a Session Called %S at Address:  %S\n", pHostNode->pwszSessionName, pwszURL);
  389.             }
  390.         }
  391.  
  392.         SAFE_DELETE_ARRAY(pwszURL);
  393.     }
  394.  
  395.     LeaveCriticalSection(&g_csHostList);
  396.  
  397. LFail:
  398.     return hr;
  399. }
  400.  
  401.  
  402.  
  403.  
  404. //-----------------------------------------------------------------------------
  405. // Name: CreateDeviceAddress()
  406. // Desc: Creates a device address
  407. //-----------------------------------------------------------------------------
  408. HRESULT CreateDeviceAddress()
  409. {
  410.     HRESULT         hr = S_OK;
  411.  
  412.     // Create our IDirectPlay8Address Device Address
  413.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  414.                                        CLSCTX_INPROC_SERVER,
  415.                                        IID_IDirectPlay8Address,
  416.                                        (LPVOID*) &g_pDeviceAddress ) ) )
  417.     {
  418.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  419.         goto LFail;
  420.     }
  421.     
  422.     // Set the SP for our Device Address
  423.     if( FAILED( hr = g_pDeviceAddress->SetSP( &CLSID_DP8SP_TCPIP ) ) )
  424.     {
  425.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  426.         goto LFail;
  427.     }
  428.  
  429. LFail:
  430.     return hr;
  431. }
  432.  
  433.  
  434.  
  435.  
  436. //-----------------------------------------------------------------------------
  437. // Name: CreateHostAddress()
  438. // Desc: Creates a host address
  439. //-----------------------------------------------------------------------------
  440. HRESULT CreateHostAddress(WCHAR* pwszHost)
  441. {
  442.     HRESULT         hr = S_OK;
  443.  
  444.     // Create our IDirectPlay8Address Host Address
  445.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  446.                                        CLSCTX_INPROC_SERVER,
  447.                                        IID_IDirectPlay8Address,
  448.                                        (LPVOID*) &g_pHostAddress ) ) )
  449.     {
  450.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  451.         goto LFail;
  452.     }
  453.     
  454.     // Set the SP for our Host Address
  455.     if( FAILED( hr = g_pHostAddress->SetSP( &CLSID_DP8SP_TCPIP ) ) )
  456.     {
  457.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  458.         goto LFail;
  459.     }
  460.  
  461.     // Set the hostname into the address
  462.     if( FAILED( hr = g_pHostAddress->AddComponent( DPNA_KEY_HOSTNAME, pwszHost,
  463.                                                    2*(wcslen(pwszHost) + 1), /*bytes*/
  464.                                                    DPNA_DATATYPE_STRING ) ) )
  465.     {
  466.         printf("Failed Adding Hostname to Host Address:  0x%X\n", hr);
  467.         goto LFail;
  468.     }
  469.  
  470. LFail:
  471.     return hr;
  472. }
  473.  
  474.  
  475.  
  476.  
  477. //-----------------------------------------------------------------------------
  478. // Name: HostSession()
  479. // Desc: Host a DirectPlay session
  480. //-----------------------------------------------------------------------------
  481. HRESULT HostSession()
  482. {
  483.     HRESULT                 hr = S_OK;
  484.     DPN_APPLICATION_DESC    dpAppDesc;
  485.     WCHAR                   wszSession[128];
  486.  
  487.  
  488.     // Prompt the user for the session name
  489.     printf("\nPlease Enter a Session Name.\n");
  490.     wscanf(L"%ls", wszSession);
  491.  
  492.     // Now set up the Application Description
  493.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  494.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  495.     dpAppDesc.guidApplication = g_guidApp;
  496.     dpAppDesc.pwszSessionName = wszSession;
  497.  
  498.     // We are now ready to host the app
  499.     if( FAILED( hr = g_pDP->Host( &dpAppDesc,            // AppDesc
  500.                                   &g_pDeviceAddress, 1,   // Device Address
  501.                                   NULL, NULL,             // Reserved
  502.                                   NULL,                   // Player Context
  503.                                   0 ) ) )                 // dwFlags
  504.     {
  505.         printf("Failed Hosting:  0x%X\n", hr);
  506.         goto LFail;
  507.     }
  508.     else
  509.     {
  510.         printf("Currently Hosting...\n");
  511.         printf("Press a key to exit\n");
  512.         _getch();
  513.     }
  514.  
  515.  
  516. LFail:
  517.     return hr;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. //-----------------------------------------------------------------------------
  524. // Name: CleanupDirectPlay()
  525. // Desc: Cleanup DirectPlay
  526. //-----------------------------------------------------------------------------
  527. void CleanupDirectPlay()
  528. {
  529.     HOST_NODE* pHostNode    = NULL;
  530.     HOST_NODE* pHostNodetmp = NULL;
  531.  
  532.     // Cleanup DirectPlay
  533.     if( g_pDP)
  534.         g_pDP->Close(0);
  535.  
  536.     // Clean up Host list
  537.     EnterCriticalSection(&g_csHostList);
  538.  
  539.     pHostNode = g_pHostList;
  540.     while( pHostNode != NULL )
  541.     {       
  542.         SAFE_RELEASE(pHostNode->pHostAddress);
  543.         SAFE_DELETE(pHostNode->pAppDesc);
  544.         SAFE_DELETE(pHostNode->pwszSessionName);
  545.  
  546.         pHostNodetmp = pHostNode;
  547.         pHostNode    = pHostNode->pNext;
  548.         SAFE_DELETE(pHostNodetmp);
  549.     }
  550.  
  551.     LeaveCriticalSection(&g_csHostList);
  552.  
  553.     SAFE_RELEASE(g_pDeviceAddress);
  554.     SAFE_RELEASE(g_pHostAddress);
  555.     SAFE_RELEASE(g_pDP);
  556.  
  557.     DeleteCriticalSection(&g_csHostList);
  558. }
  559.